package com.my.aslife.service.impl;

import com.my.aslife.exception.BusinessException;
import com.my.aslife.mapper.UserMapper;
import com.my.aslife.module.common.*;
import com.my.aslife.module.entity.Demand;
import com.my.aslife.module.entity.User;
import com.my.aslife.service.EmailService;
import com.my.aslife.service.IUserService;
import com.my.aslife.utils.Code;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.mail.MessagingException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

/**
 * @author mayuan
 * @description TODO
 */
@Service
@Slf4j
public class EmailServiceImpl implements EmailService {

    /**
     * 注入邮件工具类
     */
    @Autowired
    private JavaMailSenderImpl javaMailSender;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Value("${spring.mail.username}")
    private String sendMailer;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private IUserService userService;

    public EmailServiceImpl() {
    }

    /**
     * 检测邮件信息类
     * @param to
     * @param subject
     * @param text
     */
    private void checkMail(String to,String subject,String text) {
        if(StringUtils.isEmpty(to)) {
            throw new BusinessException(ErrorCode.EMAIL_PUSH_USERNAME_NOT_NULL);
        }
        if(StringUtils.isEmpty(subject)) {
            throw new BusinessException(ErrorCode.EMAIL_PUSH_TOPIC_NOT_NULL);
        }
        if(StringUtils.isEmpty(text)) {
            throw new BusinessException(ErrorCode.EMAIL_PUSH_CONTEXT_NOT_NULL);
        }
    }

    /**
     * 发送纯文本邮件
     * @param to
     */
    public ResponseResult sendRegisterEmail(String to) {

        String emailExistKey = RedisConstant.EMAIL_REGISTER_USER_EXIST + to;
        String emailExistFlag = stringRedisTemplate.opsForValue().get(emailExistKey);
        if (emailExistFlag != null) {
            return ResponseResult.failed(ErrorCode.EMAIL_EXISTS);
        }

        // 注册已有用户，返回错误
        Integer userNameFlag = userMapper.getUserNameFlag(to);
        if (userNameFlag > 0) {
            stringRedisTemplate.opsForValue().set(emailExistKey, "null", 1L, TimeUnit.DAYS);
            return ResponseResult.failed(ErrorCode.EMAIL_EXISTS);
        }

        // 注册邮件key
        String key = RedisConstant.EMAIL_REGISTER_CODE + to;
        // 发送邮件
        sendEmail(to, key);

        return ResponseResult.ok();
    }

    @Override
    public ResponseResult sendResetPwdEmail(String to) {

        // 重置密码key
        String key = RedisConstant.EMAIL_RESET_PWD_CODE + to;

        sendEmail(to, key);

        return ResponseResult.ok();
    }

    @Override
    public ResponseResult sendLoginEmail(String to) {

        User user = userService.queryUserByEmailOrUserName(to);
        if (user == null) {
            return ResponseResult.failed(ErrorCode.NOT_FOUND_USER);
        }

        // 登录key
        String key = RedisConstant.EMAIL_LOGIN_CODE + to;

        sendEmail(to, key);
        return ResponseResult.ok();
    }

    @Override
    public ResponseResult sendTextEmail(String to, Demand demand) {

        /** 发送主题*/
        String subject = "阿师跑腿";
        // 获取 6 位验证码
        String code = Code.getCode();
        // 发送文本内容
        String text = "【阿师跑腿】 请尽快配送订单号：" + demand.getAddressKey() + "，地址：" + demand.getAddress()
                + "，内容：" + demand.getContext();
        try {
            //true 代表支持复杂的类型
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(),true);
            //邮件发信人
            mimeMessageHelper.setFrom(sendMailer);
            //邮件收信人  1或多个
            mimeMessageHelper.setTo(to.split(","));
            //邮件主题
            mimeMessageHelper.setSubject(subject);
            //邮件内容
            mimeMessageHelper.setText(text);
            //邮件发送时间
            mimeMessageHelper.setSentDate(new Date());
            //发送邮件
            javaMailSender.send(mimeMessageHelper.getMimeMessage());
            log.info("发送邮件成功：{} -> {}",sendMailer, to);

        } catch (MessagingException e) {
            log.error("发送邮件失败：{}",e.getMessage());
        }
        return ResponseResult.ok();
    }

    /**
     * @param to 邮件号
     * @param key 发送邮件的key
     */
    private void sendEmail(String to, String key) {

        String globalIP = IPThreadLocal.getGlobalIP();
        // flag 查询 redis 内是否有验证码
        String flag = stringRedisTemplate.opsForValue().get(key);
        // 一个 ip 一天最多发送4封邮件
        String ipKey = RedisConstant.EMAIL_USER_TIMES + globalIP;
        String ipFlag = stringRedisTemplate.opsForValue().get(ipKey);

        // 一天只能发送 4 封邮件
        if (ipFlag != null && Integer.parseInt(ipFlag) <= 0) {
            throw new BusinessException(ErrorCode.EMAIL_NO_TIMES);
        } else if (ipFlag == null) {
            // 第一次发送邮件，赋值
            stringRedisTemplate.opsForValue().set(ipKey, ""+RedisConstant.EMAIL_AVAILABLE_TIMES, 1L, TimeUnit.DAYS);
        }

        // 不要频繁发邮件
        if (flag != null) {
            throw new BusinessException(ErrorCode.EMAIL_IS_FAST);
        }

        /** 发送主题*/
        String subject = "阿师跑腿";
        // 获取 6 位验证码
        String code = Code.getCode();
        // 发送文本内容
        String text = "【阿师跑腿】验证码："+ code +" 有效期5分钟";
        try {
            //true 代表支持复杂的类型
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(javaMailSender.createMimeMessage(),true);
            //邮件发信人
            mimeMessageHelper.setFrom(sendMailer);
            //邮件收信人  1或多个
            mimeMessageHelper.setTo(to.split(","));
            //邮件主题
            mimeMessageHelper.setSubject(subject);
            //邮件内容
            mimeMessageHelper.setText(text);
            //邮件发送时间
            mimeMessageHelper.setSentDate(new Date());
            //发送邮件
            javaMailSender.send(mimeMessageHelper.getMimeMessage());
            log.info("发送邮件成功：{} -> {}",sendMailer, to);

            // 设置一个邮件号 5 分钟有效
            stringRedisTemplate.opsForValue().set(key, code, RedisConstant.EMAIL_VALID_TIME, TimeUnit.MINUTES);
            // 发送次数-1
            Long increment = stringRedisTemplate.opsForValue().increment(ipKey, -1);
            log.info("globalIP 次数 : {}",increment);

        } catch (MessagingException e) {
            log.error("发送邮件失败：{}",e.getMessage());
        }
    }
}
